using System;
using System.Collections.Generic;

using log4net;

using GymManager.Exception;
using GymManager.Mechanism;
using GymManager.Persistence;
using GymManager.Persistence.DAO;
using GymManager.Persistence.VO;

using IBatisNet.DataMapper;
using IBatisNet.Common;

namespace GymManager.Business
{
    /// <summary>
    /// Class responsible by providing services regarding stock item
    /// </summary>
    public class StockItemServices
    {
        // logger instance
        private ILog _logManager = LogManager.GetLogger(typeof(StockItemServices));

        /// <summary>
        /// Method responsible by getting information about stock item in according to a given description
        /// </summary>
        /// <param name="String">stock item's description</param>
        /// <returns>StockItem - user value object matching with given description</returns>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public StockItem findByDescription(String description)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            StockItem stockItemResult = null;

            try
            {
                StockItemDAO stockItemDAO = new StockItemDAO();
                stockItemResult = stockItemDAO.findByDescription(description);
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }            
            
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }

            return stockItemResult;
        }

        /// <summary>
        /// Method responsible by getting information about stock item using its identifier
        /// </summary>
        /// <param name="Int32">stock item's identifier</param>
        /// <returns>StockItem - user value object matching with given identifier</returns>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public StockItem findByKey(Int32 id)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            StockItem stockItemResult = null;

            try
            {
                StockItemDAO stockItemDAO = new StockItemDAO();
                stockItemResult = stockItemDAO.findByKey(id);
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }

            return stockItemResult;
        }

        /// <summary>
        /// Method responsible by getting all active stock items
        /// </summary>
        /// <returns>IList - list of stock items </returns>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public IList<StockItem> findAllActive()
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            IList<StockItem> stockItemList = null;

            try
            {
                StockItemDAO stockItemDAO = new StockItemDAO();
                stockItemList = stockItemDAO.findAllActive();
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }

            return stockItemList;
        }

        /// <summary>
        /// Method responsible by adding a new stock item to database
        /// </summary>
        /// <param name="StockItem">stock item information to be saved</param>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public void create(StockItem stockItemVO)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            try
            {
                // adding stock item to database
                StockItemDAO stockItemDAO = new StockItemDAO();
                stockItemDAO.create(stockItemVO);
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }
        }

        /// <summary>
        /// Method responsible by updating an stock item to database
        /// </summary>
        /// <param name="StockItem">stock item information to be saved</param>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public void update(StockItem stockItemVO)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            try
            {
                // updating stock item to database
                StockItemDAO stockItemDAO = new StockItemDAO();
                stockItemDAO.update(stockItemVO);
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }
        }

        /// <summary>
        /// Method responsible by finding stock item using any of its properties
        /// </summary>
        /// <param name="StockItem">stock item filter vo</param>
        /// <returns>IList - list of stock item retrieved in according to filter</returns>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public IList<StockItem> findByAny(StockItem stockItemVOFilter)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            IList<StockItem> stockItemList = null;

            try
            {
                // formating information of stock item VO filter
                if (!String.IsNullOrEmpty(stockItemVOFilter.Description))
                {
                    stockItemVOFilter.Description = "%" + stockItemVOFilter.Description + "%";
                }

                // getting information about stock item
                StockItemDAO stockItemDAO = new StockItemDAO();
                stockItemList = stockItemDAO.findByAny(stockItemVOFilter);
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }

            return stockItemList;
        }

        /// <summary>
        /// Method responsible by removing an stock item from database
        /// </summary>
        /// <param name="Int32">stock item identifier</param>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public void remove(Int32 stockItemId)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            try
            {
                // removing stock item from database
                StockItemDAO stockItemDAO = new StockItemDAO();
                stockItemDAO.remove(stockItemId);
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }
        }

        #region Stock Item Purchase
        /// <summary>
        /// Method responsible by purchasing some stock items 
        /// </summary>
        /// <param name="StockItemPurchase">stock item purchase data</param>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public void purchase(StockItemPurchase stockItemPurchaseVO)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            try
            {
                // doing job inside transaction
                ISqlMapper ibatisMapper = DAOManager.getInstance();
                using (IDalSession sessionTransaction = ibatisMapper.BeginTransaction())
                {

                    // registering purchase
                    StockItemPurchaseDAO stockItemPurchaseDAO = new StockItemPurchaseDAO();
                    stockItemPurchaseDAO.create(stockItemPurchaseVO);

                    // update stock item quantity
                    StockItemDAO stockItemDAO = new StockItemDAO();
                    StockItem stockItem = stockItemDAO.findByKey(stockItemPurchaseVO.StockItemId);
                    stockItem.Quantity = stockItem.Quantity + stockItemPurchaseVO.Quantity;
                    stockItemDAO.update(stockItem);

                    // commit the transaction
                    sessionTransaction.Complete();
                }
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }
        }
        #endregion

        #region Stock Item Sales
        /// <summary>
        /// Method responsible by marking as paid the sales made by some student.
        /// </summary>
        /// <param name="IList">sales id list</param>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public void markSalesAsPaid(IList<Int32> saledIdList)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            try
            {
                // updating information about stock item sales
                StockItemSalesDAO stockItemSalesDAO = new StockItemSalesDAO();
                stockItemSalesDAO.updateSalesListAsPaid(saledIdList);
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }
        }

        /// <summary>
        /// Method responsible by selling stock items 
        /// </summary>
        /// <param name="IList">list of stock item sales value object</param>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public void sell(IList<StockItemSales> stockItemSalesList)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            try
            {
                // doing job inside transaction
                ISqlMapper ibatisMapper = DAOManager.getInstance();
                using (IDalSession sessionTransaction = ibatisMapper.BeginTransaction())
                {
                    StockItemSalesDAO stockItemSalesDAO = new StockItemSalesDAO();
                    foreach (StockItemSales stockItemSales in stockItemSalesList)
                    {
                        stockItemSalesDAO.create(stockItemSales);
                    }

                    // commit the transaction
                    sessionTransaction.Complete();
                }
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }
        }

        /// <summary>
        /// Method responsible by finding all stock items sailed which are sold to a specific 
        /// student in a given month
        /// </summary>
        /// <param name="Int32">student identifier</param>
        /// <param name="DateTime">month to be used as filter</param>
        /// <see cref="GymManager.Exception.BusinessException"/>
        public IList<StockItemSales> findStockItemSalesByStudentInAMonth(Int32 studentId, DateTime monthDate)
        {
            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("Begin Method");
            }

            IList<StockItemSales> stockItemSalesList = null;

            try
            {
                // getting information about stock item sales
                StockItemSalesDAO stockItemSalesDAO = new StockItemSalesDAO();
                stockItemSalesList = stockItemSalesDAO.findStockItemSalesByStudentInAMonth(studentId, monthDate);
            }
            catch (PersistenceException)
            {
                throw new BusinessException();
            }

            if (_logManager.IsInfoEnabled)
            {
                _logManager.Info("End Method");
            }

            return stockItemSalesList;
        }
        #endregion
    }
}
